package domain;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;

import pagemaker.ExternalProgramException;

public class PDFLibrary {
    int                       nbDocs, groupSize, currentGroupElement;
    String                    libraryFilename;
    FileWriter                pdfLibrary;
    ArrayList<PDFdoc>         ssLibrary;

    /**
     * Note the private constructor. The class must implement the Singleton
     * Pattern.
     * 
     * @param filename
     */
    private static PDFLibrary instance = null;

    private PDFLibrary(String filename) {
        nbDocs = 0;
        this.libraryFilename = filename;
        ssLibrary = new ArrayList<PDFdoc>();
    }

    /**
     * Given a filename, returns an instance of PDFLibrary. The filename is used
     * to save library's content.
     * 
     * @param filename
     * @return
     */
    public static PDFLibrary makePDFLibrary(String filename) {
        if (instance == null) {
            instance = new PDFLibrary(filename);
        }
        return instance;
    }

    /**
     * Saves the library to the disc.
     */
    public void saveLibrary() {
        try {
            FileWriter pdfLibrary = new FileWriter(libraryFilename);
            for (PDFdoc pdf : ssLibrary)
                pdfLibrary.write(pdf.toString());
            pdfLibrary.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Loads a library from the disc.
     */
    public void loadLibrary() {
        String line;
        String[] values;
        PDFdoc pdf;
        try {
            BufferedReader pdfLibrary = new BufferedReader(new FileReader(
                    libraryFilename));
            while ((line = pdfLibrary.readLine()) != null) {
                values = line.split(";");
                File file = new File(values[0]);
                try {
                    pdf = PDFdoc.makePDFdoc(file);
                    pdf.setDocumentNumber(Integer.parseInt(values[1]));
                    pdf.setTitle(values[2]);
                    pdf.addTags(values[3], ", ");
                    // pdf.setAuthors(values[3], ", ");
                    ssLibrary.add(pdf);
                } catch (ExternalProgramException e) {
                    e.printStackTrace();
                }
            }
            pdfLibrary.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Adds a document to the library.
     * 
     * @param doc
     */
    public void addDoc(PDFdoc doc) {
        doc.setDocumentNumber(nbDocs);
        ssLibrary.add(doc);
        nbDocs++;
    }

    /**
     * Removes a document from the library.
     * 
     * @param doc
     */
    public void removeDoc(PDFdoc doc) {
        ssLibrary.remove(doc);
        nbDocs--;
    }

    /**
     * Returns the number of documents present in the library.
     * 
     * @return
     */
    public int getNumberOfDocuments() {
        return nbDocs;
    }

    /**
     * Given a set of tags, select the documents that have at least one of these
     * tags. The result is a possibly large set of documents referred as the
     * "selection".
     * 
     * @param tags
     */
    public void selectDocsWithOneOfTheseTags(ArrayList<String> tags) {
        // TODO: RNA - Falta implementar
    }

    /**
     * Given a set of tags, select the documents that have all the tags. The
     * result is a possibly large set of documents referred as the "selection".
     * 
     * @param tags
     */
    public void selectDocsWithAllTheseTags(ArrayList<String> currentTags) {
        // TODO: RNA - Falta implementar
    }

    /**
     * The selection is divided into subsets of documents called "groups". This
     * method returns the first group of the selection.
     * 
     * @return
     */
    public List<PDFdoc> getFirstGroup() {
        List<PDFdoc> list = new ArrayList<PDFdoc>();
        for (int i = 0; i < this.groupSize && i < ssLibrary.size(); i++) {
            list.add(ssLibrary.get(i));
            this.currentGroupElement = i;
        }
        return list;
    }

    /**
     * Returns the next group of documents.
     * 
     * @return
     */
    public List<PDFdoc> getNextGroup() {
        int startGroup = this.currentGroupElement;
        int endGroup = this.currentGroupElement + this.groupSize;

        List<PDFdoc> list = new ArrayList<PDFdoc>();
        for (int i = startGroup; i < endGroup && i < ssLibrary.size(); i++) {
            list.add(ssLibrary.get(i));
            this.currentGroupElement = i;
        }
        return list;
    }

    /**
     * Returns the previous group of documents.
     * 
     * @return
     */
    public List<PDFdoc> getPreviousGroup() {
        int startGroup = this.currentGroupElement - this.groupSize;
        int endGroup = this.currentGroupElement;

        List<PDFdoc> list = new ArrayList<PDFdoc>();
        for (int i = startGroup; i < endGroup && i < ssLibrary.size(); i++) {
            list.add(ssLibrary.get(i));
            this.currentGroupElement = i;
        }
        return list;
    }

    /**
     * Changes the size (number of elements) that from a group of documents.
     * 
     * @param size
     */
    public void setGroupSize(int size) {
        this.groupSize = size;
    }

    /**
     * Returns the number of the current group of documents.
     * 
     * @return
     */
    public int getCurrentGroupNumber() {
        // TODO: RNA - Falta implementar
        return (int) Math.ceil(currentGroupElement / groupSize);
    }

    /**
     * Returns the number of groups in the selection
     * 
     * @return
     */
    public int nbGroupsInSelection() {
        // TODO: RNA - Falta implementar
        return 0;
    }

    /**
     * Returns the number of elements in the selection.
     * 
     * @return
     */
    public int selectionSize() {
        // TODO: RNA - Falta implementar
        return 0;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (PDFdoc pdf : ssLibrary)
            sb.append(pdf.toString() + "\n");
        return sb.toString();
    }

}